<?php
/**
 *
 * example目录下为简单的支付样例，仅能用于搭建快速体验微信支付使用
 * 样例的作用仅限于指导如何使用sdk，在安全上面仅做了简单处理， 复制使用样例代码时请慎重
 * 请勿直接直接使用样例对外提供服务
 *
 **/
require_once dirname(dirname ( __FILE__ ))."/lib/WxPay.Api.php";
require_once "WxPay.Config.php";
/**
 *
 * JSAPI支付实现类
 * 该类实现了从微信公众平台获取code、通过code获取openid和access_token、
 * 生成jsapi支付js接口所需的参数、生成获取共享收货地址所需的参数
 *
 * 该类是微信支付提供的样例程序，商户可根据自己的需求修改，或者使用lib中的api自行开发
 *
 * @author widy
 *
 */
class JsApiPay
{
    /**
     *
     * 网页授权接口微信服务器返回的数据，返回样例如下
     * {
     *  "access_token":"ACCESS_TOKEN",
     *  "expires_in":7200,
     *  "refresh_token":"REFRESH_TOKEN",
     *  "openid":"OPENID",
     *  "scope":"SCOPE",
     *  "unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"
     * }
     * 其中access_token可用于获取共享收货地址
     * openid是微信支付jsapi支付接口必须的参数
     * @var array
     */
    public $data = null;

    /**
     *
     * 通过跳转获取用户的openid，跳转流程如下：
     * 1、设置自己需要调回的url及其其他参数，跳转到微信服务器https://open.weixin.qq.com/connect/oauth2/authorize
     * 2、微信服务处理完成之后会跳转回用户redirect_uri地址，此时会带上一些参数，如：code
     *
     * @return 用户的openid
     */
    public function GetOpenid($code)
    {
        $openid = $this->getOpenidFromMp($code);
        return $openid;
    }

    /**
     *
     * 获取jsapi支付的参数
     * @param array $UnifiedOrderResult 统一支付接口返回的数据
     * @throws WxPayException
     *
     * @return json数据，可直接填入js函数作为参数
     */
    public function GetJsApiParameters($UnifiedOrderResult)
    {
        if(!array_key_exists("appid", $UnifiedOrderResult)
            || !array_key_exists("prepay_id", $UnifiedOrderResult)
            || $UnifiedOrderResult['prepay_id'] == "")
        {
            throw new WxPayException("参数错误");
        }

        $jsapi = new WxPayJsApiPay();
        $jsapi->SetAppid($UnifiedOrderResult["appid"]);
        $timeStamp = time();
        $jsapi->SetTimeStamp("$timeStamp");
        $jsapi->SetNonceStr(WxPayApi::getNonceStr());
        $jsapi->SetPackage("prepay_id=" . $UnifiedOrderResult['prepay_id']);

        $config = new WxPayConfig();
        $jsapi->SetPaySign($jsapi->MakeSign($config));
        $parameters = json_encode($jsapi->GetValues());
        return $parameters;
    }

    /**
     *
     * 通过code从工作平台获取openid机器access_token
     * @param string $code 微信跳转回来带上的code
     *
     * @return openid
     */
    public function GetOpenidFromMp($code)
    {
        $url = $this->jscode2session($code);

        //初始化curl
        $ch = curl_init();
        $curlVersion = curl_version();
        $config = new WxPayConfig();
        $ua = "WXPaySDK/3.0.9 (".PHP_OS.") PHP/".PHP_VERSION." CURL/".$curlVersion['version']." "
            .$config->GetMerchantId();

        //设置超时
        curl_setopt($ch, CURLOPT_TIMEOUT, 30);
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER,FALSE);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST,FALSE);
        curl_setopt($ch, CURLOPT_USERAGENT, $ua);
        curl_setopt($ch, CURLOPT_HEADER, FALSE);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);

        $proxyHost = "0.0.0.0";
        $proxyPort = 0;
        $config->GetProxy($proxyHost, $proxyPort);
        if($proxyHost != "0.0.0.0" && $proxyPort != 0){
            curl_setopt($ch,CURLOPT_PROXY, $proxyHost);
            curl_setopt($ch,CURLOPT_PROXYPORT, $proxyPort);
        }
        //运行curl，结果以jason形式返回
        $res = curl_exec($ch);
        curl_close($ch);
        //取出openid
        $data = json_decode($res,true);
        $this->data = $data;
        if(isset($data['openid']) && $data['openid']){
            return $data['openid'];
        }else{
            return '';
        }
    }

    /**
     *
     * 拼接签名字符串
     * @param array $urlObj
     *
     * @return 返回已经拼接好的字符串
     */
    private function ToUrlParams($urlObj)
    {
        $buff = "";
        foreach ($urlObj as $k => $v)
        {
            if($k != "sign"){
                $buff .= $k . "=" . $v . "&";
            }
        }

        $buff = trim($buff, "&");
        return $buff;
    }

    /**
     *
     * 获取地址js参数
     *
     * @return 获取共享收货地址js函数需要的参数，json格式可以直接做参数使用
     */
    public function GetEditAddressParameters()
    {
        $config = new WxPayConfig();
        $getData = $this->data;
        $data = array();
        $data["appid"] = $config->GetAppId();
        $data["url"] = "http://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
        $time = time();
        $data["timestamp"] = "$time";
        $data["noncestr"] = WxPayApi::getNonceStr();
        $data["accesstoken"] = $getData["access_token"];
        ksort($data);
        $params = $this->ToUrlParams($data);
        $addrSign = sha1($params);

        $afterData = array(
            "addrSign" => $addrSign,
            "signType" => "sha1",
            "scope" => "jsapi_address",
            "appId" => $config->GetAppId(),
            "timeStamp" => $data["timestamp"],
            "nonceStr" => $data["noncestr"]
        );
        $parameters = json_encode($afterData);
        return $parameters;
    }

    /**
     *
     * 构造获取code的url连接
     * @param string $redirectUrl 微信服务器回跳的url，需要url编码
     *
     * @return 返回构造好的url
     */
    private function _CreateOauthUrlForCode($redirectUrl)
    {
        $config = new WxPayConfig();
        $urlObj["appid"] = $config->GetAppId();
        $urlObj["redirect_uri"] = "$redirectUrl";
        $urlObj["response_type"] = "code";
        $urlObj["scope"] = "snsapi_base";
        $urlObj["state"] = "STATE"."#wechat_redirect";
        $bizString = $this->ToUrlParams($urlObj);
        return "https://open.weixin.qq.com/connect/oauth2/authorize?".$bizString;
    }

    /**
     *
     * 构造获取open和access_toke的url地址
     * @param string $code，微信跳转带回的code
     *
     * @return 请求的url
     */
    private function __CreateOauthUrlForOpenid($code)
    {
        $config = new WxPayConfig();
        $urlObj["appid"] = $config->GetAppId();
        $urlObj["secret"] = $config->GetAppSecret();
        $urlObj["code"] = $code;
        $urlObj["grant_type"] = "authorization_code";
        $bizString = $this->ToUrlParams($urlObj);
        return "https://api.weixin.qq.com/sns/oauth2/access_token?".$bizString;
    }

    public function jscode2session($jscode)
    {
        $config = new WxPayConfig();
        $urlObj=array('appid' => $config->GetAppId(), 'secret' => $config->GetAppSecret(), 'js_code' => $jscode, 'grant_type' => 'authorization_code');
        $bizString = $this->ToUrlParams($urlObj);
        return "https://api.weixin.qq.com/sns/jscode2session?".$bizString;
        //{ ["session_key"]=> string(24) "qbdVPVlsGnhSYn4D5QSetA==" ["openid"]=> string(28) "oxpsF7MhZ12AK0gxL6B95_VGop7Y" }
    }

    public function decryptUserInfo($sessionKey, $iv, $encryptedData)
    {
        $r = "";
        $errCode =$this->decryptData($sessionKey,$encryptedData, $iv, $r);
        $r = json_decode($r, true);
        var_dump($r);
        $result = array();
        if ($errCode == 0 && is_array($r) && !empty($r) && !empty($r['openId'])) {
            // 统一格式
            $result = array(
                'openid' => $r['openId'],
                'nickname' => $r['nickName'],
                'sex' => $r['gender'],
                'province' => $r['province'],
                'city' => $r['city'],
                'headimgurl' => $r['avatarUrl'],
                'unionid' => isset($r['unionId']) ? $r['unionId'] : '',
                'country' => isset($r['country']) ? $r['country'] : '',
            );
        }
        return $result;
    }
    public function decryptData($sessionKey, $encryptedData, $iv, &$data )
    {
        if (strlen($sessionKey) != 24) {
            return -41001;
        }
        $aesKey=base64_decode($sessionKey);


        if (strlen($iv) != 24) {
            return -41002;
        }
        $aesIV = base64_decode($iv);

        $aesCipher=base64_decode($encryptedData);

        $result=openssl_decrypt( $aesCipher, "AES-128-CBC", $aesKey, 1, $aesIV);

        $dataObj=json_decode( $result );
        if ($dataObj == NULL) {
            return -41003;
        }
        $data = $result;
        return 0;
    }

    public function httpRequest($url, $data = '', $method = 'get')
    {
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
        if ($method == 'post') {
            curl_setopt($curl, CURLOPT_POST, 1);
            curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
        }
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        $output = curl_exec($curl);
        curl_close($curl);
        return $output;
    }

    public function getPhoneNumber($code){
        $url = 'https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token='.$this->getAccessToken();
        $res = json_decode($this->httpRequest($url,json_encode(['code'=>$code]),'post'), true);
        if($res['errcode']==0){
            return $res['phone_info']['purePhoneNumber'];
        }else{
            return '';
        }
    }

    public function getAccessToken()
    {;
        $accessToken = '';
        $data =  cache('access_token_wx');
        if (!$data) {
            $config = new WxPayConfig();
            $appId=$config->GetAppId();
            $appSecret=$config->GetAppSecret();
            $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$appId}&secret={$appSecret}";
            $res = json_decode($this->httpRequest($url), true);
            if (isset($res['access_token']) && $res['access_token']) {
                $accessToken = $res['access_token'];
                $cacheData = array('expire_time' => time() + 7000, 'access_token' => $accessToken);
                cache('access_token_wx',  json_encode($cacheData),7000);
            }
        } else {
            $data = json_decode($data, true);
            if (isset($data['access_token']) && $data['access_token']) {
                $accessToken = $data['access_token'];
            }
        }
        return $accessToken;
    }
    public function getQRCode($params)
    {
        $accessToken = $this->getAccesstoken();
        $url = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token={$accessToken}";
        return $this->httpRequest($url,json_encode($params),'post');

    }

    public function getSignUrl($order_id,$channel,$type){
        //海报
        $path = 'upload/qrcode/';
        if (!is_dir($path)) {
            mkdir($path, 0777, true);
        }
        $qrcode = $path . 'qr_'.$channel.'_' .$type. md5($order_id) . '.jpg';
        $page='accepter/pages/approval/index';
        $base64_encode="order_id={$order_id}&type=".$type;
        if (!file_exists($qrcode)) {
            $content = $this->getQRCode(['scene' =>$base64_encode, 'page' => $page, 'check_path' => false, 'width' => 430, 'env_version' => 'release']);
            if (!empty($content)) {
                file_put_contents($qrcode, $content);
            }
            if (!file_exists($qrcode)) {
                $qrcode = '';
            }
        }
        return $qrcode;
    }

    public function getDiscountUrl($order_id,$channel,$type){
        require_once '/www/wwwroot/stop/public/plugins/pay/addons/wechat/example/phpqrcode/phpqrcode.php';
        $path = 'upload/qrcode/';
        if (!is_dir($path)) {
            mkdir($path, 0777, true);
        }
        $qrcode = $path . 'qr_'.$channel.'_' .$type. md5($order_id) . '.jpg';
        if (!file_exists($qrcode)) {
            $content = QRcode::png($order_id);
            if (!empty($content)) {
                file_put_contents($qrcode, $content);
            }
            if (!file_exists($qrcode)) {
                $qrcode = '';
            }
        }
        return $qrcode;
    }



}
